#pragma once
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string>
#include<time.h>
#include <stdarg.h>

int _TYPE_SCREEN = 1;
int _TYPE_FILE = 0;


#define _DEFAULT_FILENAME "./log.txt"


//宏支持可变参数
#define lg(level,format,...) do{LOG::Log lg(level,__FILE__,__LINE__,format,##__VA_ARGS__);}while(0)

namespace LOG
{
    enum
    {
        DEBUG = 1,
        INFO,
        WARNING,
        ERROR,
        FATAL
    };
    void TO_SCREEN()
    {
         _TYPE_SCREEN = 1;
         _TYPE_FILE = 0;
    }

     void TO_FILE()
    {
         _TYPE_SCREEN = 0;
         _TYPE_FILE = 1;
    }

    class Log
    {
    public:
        Log(int level,std::string filename,int filenumber,const char* format,...)
         :_pid(getpid()),
         _filename(filename),
         _filenumber(filenumber)
        {
            //初始化_level
            InitLevel(level);
            //初始化_cur_time
            InitTime();
            //初始化_message
            va_list ap;
            va_start(ap,format);
            char log_info[1024];
            vsnprintf(log_info,sizeof(log_info),format,ap);
            va_end(ap);
            _message = log_info;
            //打印日志
            PrintLog();
        }
       
    private:
        std::string _level;
        pid_t _pid;
        std::string _filename;
        int _filenumber;
        struct tm _cur_time;
        std::string _message;
        void InitLevel(int level)
        {
            switch(level)
            {
                case DEBUG:
                    _level = "DEBUG";;
                    break;
                case INFO:
                    _level = "INFO";
                    break;
                case WARNING:
                    _level = "WARNING";
                    break;
                case ERROR:
                    _level = "ERROR";
                    break;
                case FATAL:
                    _level = "FATAL";
                    break;
                default:
                    _level = "UNKNOW";
;            };
        }

        void InitTime()
        {
            struct tm* tmp;
            time_t timer = time(nullptr);
            tmp =localtime(&timer);
            _cur_time = *tmp;
        }

        void PrintScreen()
        {   
             printf("[%s][%d][%s][%d][%d-%02d-%02d %02d:%02d:%02d]%s\n",
            _level.c_str(),
            _pid,
            _filename.c_str(),
            _filenumber,
            (_cur_time.tm_year+1900),_cur_time.tm_mon+1,_cur_time.tm_mday,
            _cur_time.tm_hour,_cur_time.tm_min,_cur_time.tm_sec,
            _message.c_str()
            );
            fflush(stdout);
        }

        void PrintFile(std::string filename = _DEFAULT_FILENAME)
        {   
            FILE*fd = fopen(filename.c_str(),"a+");
            if(fd==NULL)
            {
                perror("fopen failed...\n");
                return;
            }
            //冲刷标准输出缓冲区
            fflush(stdout);
            //保存标准输出
            int Screen = dup(1);
            //重定向到文件
            dup2(fd->_fileno,1);
            //打印数据
            PrintScreen();
            //恢复重定向
            dup2(Screen,1);
        }

        void PrintLog()
        {
            if(_TYPE_SCREEN)
            {
                PrintScreen();
            }
            else if(_TYPE_FILE)
            {
                PrintFile();
            }
           
        }
    };
};